#include "libcard.h"
#include "yangchengtong.h"

#define MAX_BUF_SIZE		128
#define DEBUG

#define STX 0x02
#define ETX 0x03
#define YCT_TERMINAL_STX 0xBA
#define YCT_CARD_STX 0xBD

int card_state = MOC_ERROR_CARD_NOTAG; // 读卡器读卡的状态

typedef struct {
	rf_card* card;
	int uart_fd;
	pthread_mutex_t* card_mutex;
	pthread_t thread_id;
	bool seek_card_flag;//false:退出寻卡 true:开始寻卡
}card_t;

card_t g_card;
struct yct_card yct; //羊城通数据结构体
bool isSeek_flag = true;//true可以寻卡  false不可以寻卡
unsigned char serverCode[2]={0x01,0x00};


void clear_card_info(void)
{
	memset(&(g_card.card->UIDLen),0,sizeof(unsigned char));
	memset(g_card.card->cardUID,0,sizeof(g_card.card->cardUID));
	memset(g_card.card->cmd1,0,sizeof(g_card.card->cmd1));
	memset(g_card.card->cmd2,0,sizeof(g_card.card->cmd2));
	memset(g_card.card->cmd3,0,sizeof(g_card.card->cmd3));
	memset(g_card.card->cardNUM,0,sizeof(g_card.card->cardNUM));
	memset(&(g_card.card->available_money),0,sizeof(unsigned int));
	memset(&(g_card.card->ver),0,sizeof(char));
	memset(&(g_card.card->tag),0,sizeof(char));
	memset(&(g_card.card->rand),0,sizeof(int));
	memset(&(g_card.card->mac),0,sizeof(int));
}

unsigned int inttoBCD(int m)
{
	unsigned int r=0;
	int a;
	int  i = 0;
	while(m)
	{
		a=m %10;
		m=m/10;
		a=a<<(4*i);
		r |= a;
		i++;
	}
	return r;
}

int get_valid_bcc(const uint8* buf, const uint32 len)
{
	uint32 index = 0;
	uint8 bcc = 0;
	uint32 data_len = 0;
	uint32 i = 0;

	for(index=0; index<len; index++){
		if(buf[index] == STX)
			break;
	}
	if(index>= len){
		printf("##Libcard YCT## get bcc fail, due to trash data!\n");
		return -1;
	}


	index++;
	data_len = (buf[index]<<8) | buf[index+1];
	index += 2;
	for(i=0; i<data_len; i++){
		bcc ^= buf[index+i];
	}

	return bcc;
}

int get_valid_xor_cs(const uint8* buf, const uint32 len)
{
	int cs = 0;
	int data_len = 0;
	int i = 0;

	if(buf == NULL){
		printf("##Libcard YCT## get valid xor cs fail, due to buf is null!!!\n");
		return -1;
	}

	if( (buf[0] != YCT_CARD_STX) && (buf[0] != YCT_TERMINAL_STX)){
		printf("##Libcard YCT##get valid xor cs fail, due to none yct protocol buf[0]=%02x !!!\n",buf[0]);
		return -1;
	}

	data_len = buf[1]+1;//buf[1]+2-1  +Header+Len-Checksum
	for(i=0; i<data_len; i++)
		cs = cs^buf[i];

	return cs;
}

int  analysis_data(const unsigned char* buf, int dataLen, struct Msg_Card_to_Terminal* msg)
{
	int index = 0;
	if(buf == NULL || msg == NULL){
		printf("##Libcard YCT## analysis data error, due to para is null!!!\n");
		return 1;
	}
	if(buf[0] != YCT_CARD_STX){
		printf("##Libcard YCT## analysis data error, due to no yct protocol , buf[0]=%02x !!!\n",buf[0]);
		return 1;
	}
	msg->header = buf[index++];
	msg->dataLen = buf[index++]-3;
	msg->command = buf[index++];
	msg->status = buf[index++];
	memcpy(msg->data,&buf[index],msg->dataLen);
	index += msg->dataLen;
	msg->cs = buf[index];

	return 0;
}

int creat_yct_frame(unsigned char*buf, int bufLen, struct Msg_Terminal_to_Card* msg)
{
	int index = 0;
	int pos = 0;

	if(buf == NULL || msg == NULL){
		printf("##Libcard YCT## create yct frame error, due to para is null!!!\n");
		return 1;
	}

	if(bufLen < msg->dataLen){
		printf("##Libcard YCT## create yct frame error, due to buf  too short!!!\n");
		return 1;
	}

	memset(buf,0,bufLen);
	buf[index++] = msg->header;
	pos = index++;
	buf[index++] = msg->command;
	memcpy(&buf[index],msg->data,msg->dataLen);
	index += msg->dataLen;
	buf[pos] = msg->dataLen+2;
	buf[index] = get_valid_xor_cs(buf,bufLen);
	msg->frameLen = index+1;

	return 0;
}

int is_recv_complete(uint8* buf, int recLen)
{

	if(buf == NULL){
		return -1;
	}

	if(buf[0] != YCT_CARD_STX){
		printf("##Libcard YCT##pending recv complete fail,  due to none yct protocol buf[0]=%02x !!!\n",buf[0]);
		return -1;
	}

	if(recLen >= (buf[1]+2))
		return 0;

	return 1;
}

int uart_send(const int fd, const uint8 *buf, const uint32 len)
{
	int sended = 0;
	int i;

	if((fd<=0) || (buf==NULL) ){
		printf("##Libcard YCT## uart send fail,due to para err!\n");
		return -1;
	}

	sended = write(fd, buf, len);
	if( sended <= 0){
		printf("##Libcard YCT##--Port send [%d] error.\n ", sended);
		g_card.card->errcode = 1;//通信异常
	}

#ifdef DEBUG
	printf("CARD SEND DATA[%03d] -->", sended);
	for(i=0; i < sended; i++) {
		printf("%02x ", buf[i]);
	}
	printf("\n");
#endif
	return sended;
}


int listen_recv(const int fd, uint8 *buf, int rlen, int timeout)
{
	int len = 0, total_len = 0;
	int count =0;
	int ret;
	int i = 0;
	fd_set fdset;
	int check_ret = -1;
	uint8 *p = NULL;
	struct timeval tm;

	if (fd < 0 || rlen<0 || rlen> MAX_BUF_SIZE){
		printf(" ##Libcard YCT## listen_recv fail, due to param err !\n");
		return -1;
	}

	p = buf;
	tm.tv_sec = timeout/1000;
	tm.tv_usec = (timeout%1000)*1000;

	while(count<3)
	{
		FD_ZERO(&fdset);
		FD_SET(fd, &fdset);
		ret = select(fd + 1, &fdset, NULL, NULL, &tm);
		if(ret < 0){
			perror("##Libcard YCT## select failued !\n ");
			break;
		}
		else if(ret == 0){
			++count; //timeout
		}
		else if(FD_ISSET(fd, &fdset)){
			rlen = rlen-len;
			if(rlen <= 0)
				break;//buffer已接满

			len = read(fd, buf, rlen);
			if(len < 0)
				break;

			total_len += len;
			check_ret = is_recv_complete(p,total_len);
			if(check_ret == 0)
				break;
			else if(check_ret == 1){
				buf = p+total_len;
				continue;
			}
			else{
				memset(p,0,total_len);
				printf("##Libcard YCT## Recv Trash Data\n");
				total_len = 0;
				break;
			}
		}
	}

	if(total_len <= 0){
#ifdef DEBUG
		printf("##Libcard YCT## listen_recv fail: without recv data or recv err!!!\n");
#endif
		return total_len;
	}

	int bcc1 = 0,bcc2 = 0;
	bcc1 = get_valid_xor_cs(p,total_len);
	bcc2 = p[total_len-1];
#ifdef DEBUG
	printf("CARD RECV DATA[%03d]-->",total_len);
	for(i=0; i<total_len; i++){
		printf("%02x ",p[i]);
		//		if(i== total_len/2)
		//			printf("\n");
	}
	printf("\n");
	printf("##Libcard YCT## card recv data bbc1=%d, bbc2=%d \n",bcc1,bcc2);
#endif
	if((bcc1 != bcc2) || (bcc1 == -1)){
		printf("##Libcard YCT## card recv data error,  bbc1=%d, bbc2=%d \n",bcc1,bcc2);
		return -1;
	}
	return total_len;
}

int port_open(card_uart_para *port)
{
	int fd = 0;
	card_uart_para *com = port;

	if(NULL == com)	return -1;

	//打开串口设备
	fd = open(com->name, O_RDWR|O_NOCTTY|O_NONBLOCK);
	if(fd < 0) {
		printf("##Libcard YCT##--Open PORT: [%s] failure.\n", com->name);
	}
	return fd;
}

int speed_to_flag(int speed)
{
	uint32 i;
	int cnt = 0;

	for (i = 0; i < sizeof(speed_arr)/sizeof(int); i++) {
		cnt = (speed - speed_arr[i]);
		if ( cnt == 0)
			return baudflag_arr[i];
	}

	printf("##Libcard YCT##--Unsupported baudrate, use 9600 instead!\n");
	return B9600;
}

int port_setup(int fd, card_uart_para *port)
{
	card_uart_para *com = port;
	struct termios old_tio, new_tio;
	int baud_rate = 0;

	if(fd < 0)		return -1;
	if(NULL == com)		return -1;

	tcgetattr(fd, &old_tio);
	bzero(&new_tio, sizeof(struct termios));
	new_tio.c_cflag |= (CLOCAL | CREAD);

	//设置波特率
	baud_rate = speed_to_flag(com->baud);
	new_tio.c_cflag |= baud_rate;
	//设置停止位
	switch(com->stop_bits) {
	case 1:
		new_tio.c_cflag &= ~CSTOPB;
		break;
	case 2:
		new_tio.c_cflag |= CSTOPB;
		break;
	default:
		printf("##Libcard YCT##--PORT stop bits set error. use default.\n");
		new_tio.c_cflag &= ~CSTOPB;
		break;
	}

	//设置奇偶校验
	switch(com->parity) {
	case 0://无校验
		new_tio.c_cflag &= ~PARENB;
		break;
	case 1://奇校验
		new_tio.c_cflag |= (PARENB | PARODD);
		break;
	case 2://偶校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		break;
	case 3://MARK校验
		new_tio.c_cflag |= (PARENB | PARODD);
		new_tio.c_cflag |= CMSPAR;
		break;
	case 4://SPACE校验
		new_tio.c_cflag |= PARENB;
		new_tio.c_cflag &= ~PARODD;
		new_tio.c_cflag |= CMSPAR;
		break;
	default:
		printf("##Libcard YCT##--PORT parity set error. use default.\n");
		new_tio.c_cflag &= ~PARENB;
		break;
	}
	new_tio.c_cflag &= ~CSIZE;
	switch(com->data_bits) {
	case 5:
		new_tio.c_cflag |= CS5;
		break;
	case 6:
		new_tio.c_cflag |= CS6;
		break;
	case 7:
		new_tio.c_cflag |= CS7;
		break;
	case 8:
		new_tio.c_cflag |= CS8;
		break;
	default:
		printf("##Libcard YCT##--PORT data bits set error. use default.\n");
		new_tio.c_cflag |= CS8;
		break;
	}

	//设置无硬件流控
	new_tio.c_cflag &= ~CRTSCTS;
	new_tio.c_lflag = 0;
	new_tio.c_oflag = 0;
	new_tio.c_cc[VMIN] = 1;
	new_tio.c_cc[VTIME] = 0;
	new_tio.c_iflag &= ~(IXON | IXOFF | IXANY);

	cfsetispeed(&new_tio, baud_rate);
	cfsetospeed(&new_tio, baud_rate);
	tcsetattr(fd, TCSANOW, &new_tio);
	tcflush(fd, TCIFLUSH);

	return 0;
}

//延时器
void setTimer(unsigned int seconds, unsigned int mseconds)
{
	struct timeval temp;

	temp.tv_sec = seconds + (mseconds/1000);
	temp.tv_usec = (mseconds%1000)*1000;

	select(0, NULL, NULL, NULL, &temp);

	return ;
}

//周期性寻卡, ,同时检测读卡器的通信是否断开
void* protocol_seek_card(void* arg)
{
	struct Msg_Card_to_Terminal recMsg;
	struct Msg_Terminal_to_Card sendMsg;
	uint8 data[MAX_BUF_SIZE] = {0};
	static int set_serverCode_flag = 1;// 设置服务商代码标示 0:表示设置  1:表示没设置
	int dataLen = 0;
	int re_len = 0;
	int i = 0;
	int index = 0;
	int err_count = 0;

	while(1){		
		setTimer(1,0);
		if(!isSeek_flag)
			continue;

		printf("##Libcard YCT## seek card state: errcode=%02d  card_state:%02x \n",g_card.card->errcode,card_state);

		pthread_mutex_lock(g_card.card_mutex);
		if(set_serverCode_flag == 1){
			card_state = MOC_ERROR_CARD_NOTAG;
			dataLen = 0;
			memset(data,0,sizeof(data));
			memset(&sendMsg,0,sizeof(sendMsg));
			sendMsg.header = YCT_TERMINAL_STX;
			sendMsg.command = 0x61;
			sendMsg.data[dataLen++] = serverCode[0];
			sendMsg.data[dataLen++] = serverCode[1];
			sendMsg.dataLen = dataLen;
			creat_yct_frame(data,sizeof(data),&sendMsg);
			if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
				printf("##Libcard YCT## seek card   send error\n");
				g_card.card->errcode = 1;//通信异常
				set_serverCode_flag = 1;
				pthread_mutex_unlock(g_card.card_mutex);
				continue;
			}

			memset(data,0,sizeof(data));
			re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
			if(re_len <= 0){
				printf("##Libcard YCT## seek card  listen_recv timeout or error!\n");
				if(err_count >= 2){
					g_card.card->errcode = 1;//通信异常
					set_serverCode_flag = 1;
					err_count = 0;
				}
				err_count++;

				pthread_mutex_unlock(g_card.card_mutex);
				continue;
			}

			analysis_data(data,re_len,&recMsg);
			if(recMsg.status == MOC_ERROR_NORMAL){
				set_serverCode_flag = 0;
				printf("##Libcard YCT## set server code success!!!\n");
			}

		}

		dataLen = 0;
		//		yct.card_state = MOC_ERROR_CARD_NOTAG; //每次读卡之前 默认没卡
		//		card_state = MOC_ERROR_CARD_NOTAG;
		memset(data,0,sizeof(data));
		memset(&sendMsg,0,sizeof(sendMsg));

		sendMsg.header = YCT_TERMINAL_STX;
		sendMsg.command = 0xE7;
		sendMsg.data[dataLen++] = yct.app_flag; //00：普通消费 01：复合消费
		sendMsg.dataLen = dataLen;
		creat_yct_frame(data,sizeof(data),&sendMsg);

		if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
			printf("##Libcard YCT## seek card   send error\n");
			g_card.card->errcode = 1;//通信异常
			set_serverCode_flag = 1;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}

		memset(data,0,sizeof(data));
		re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
		if(re_len <= 0){
			printf("##Libcard YCT## seek card  listen_recv timeout or error!\n");
			if(err_count >= 2){
				g_card.card->errcode = 1;//通信异常
				set_serverCode_flag = 1;
				err_count = 0;
			}
			err_count++;
			pthread_mutex_unlock(g_card.card_mutex);
			continue;
		}
		analysis_data(data,re_len,&recMsg);
		yct.card_state = recMsg.status;
		index = 0;

		switch(recMsg.status){
		case MOC_ERROR_NORMAL:{
			yct.card_info.wallet_type =recMsg. data[index++];

			for(i=0;i<8;i++)
				yct.card_info.cardNum[i] = recMsg.data[index++];

			for(i=0;i<8;i++)
				yct.card_info.logicNum[i] = recMsg.data[index++];

			yct.card_info.balance = (recMsg.data[index]<<24) |(recMsg.data[index+1]<<16)|(recMsg.data[index+2]<<8)|(recMsg.data[index+3]);
			index += 4;

			yct.card_info.card_count = (recMsg.data[index]<<8) | (recMsg.data[index+1]);
			index += 2;

			yct.card_info.card_type =  (recMsg.data[index]<<8) | (recMsg.data[index+1]);
			index += 2;

			yct.card_info.money_low_limit = recMsg. data[index++];

			yct.card_info.money_up_limit = (recMsg. data[index]<<16) |  (recMsg. data[index+1]<<8) | (recMsg. data[index+2]);
			index += 3;

			yct.card_info.actual_balance = yct.card_info.balance - (yct.card_info.money_low_limit*100);
			if(yct.card_info.actual_balance >= 0)
				yct.card_info.over_balance = yct.card_info.money_low_limit*100;
			else
				yct.card_info.over_balance = (yct.card_info.money_low_limit*100) + yct.card_info.actual_balance;


			yct.card_info.deposit =  (recMsg.data[index]<<24) |(recMsg.data[index+1]<<16)|(recMsg.data[index+2]<<8)|(recMsg.data[index+3]);
			index +=4;

			yct.card_info.SAK = recMsg. data[index++];

			yct.card_info.ATQA[0] = recMsg. data[index++];
			yct.card_info.ATQA[1] = recMsg. data[index++];

			yct.card_info.area_sub_code = recMsg. data[index++];

			for(i=0;i<8;i++)
				yct.card_info.area_card_num[i] = recMsg. data[index++];

			yct.card_info.area_card_type =  (recMsg.data[index]<<8) | (recMsg.data[index+1]);
			index += 2;

			for(i=0;i<4;i++)
				yct.card_info.area_card_valid_date[i] = recMsg. data[index++];

			yct.card_info.area_sub_code = recMsg. data[index++];

			//#ifdef DEDUCTION_FEE
			//			for(i=0; i<35; i++){//此处判断读卡器和卡片是用作普通消费还是复合消费
			//				if (recMsg.data[index+i] != 0)
			//					break;
			//			}
			//
			//			if(i>=35){
			//				//				yct.app_flag=0x00;//全0为普通消费
			//				printf("##Libcard YCT##读卡器为普通消费读卡器，无法使用!!!\n");
			//				g_card.card->errcode = 1;
			//				pthread_mutex_unlock(g_card.card_mutex);
			//				continue;
			//			}
			//			else{
			//				yct.app_flag=0x01;//为复合消费
			//				//printf("##Libcard YCT##复合消费......i[%d]=%02x\n",i,recMsg.data[index+i]);
			//			}
			//#endif

			for(i=0;i<2;i++)
				yct.card_info.app_record.operator_code[i] = recMsg.data[index++];

			yct.card_info.app_record.record_ver = recMsg.data[index++];

			yct.card_info.app_record.record_flag = recMsg.data[index++];

			yct.card_info.app_record.record_protocol_len = recMsg.data[index++];

			for(i=0;i<8;i++)
				yct.card_info.app_record.devNum[i] = recMsg.data[index++];

			yct.card_info.app_record.devState = recMsg.data[index++];

			for(i=0;i<4;i++)
				yct.card_info.app_record.trade_serial_num[i] = recMsg.data[index++];

			for(i=0;i<7;i++)
				yct.card_info.app_record.trade_time[i] = recMsg.data[index++];

			//printf("PSAM:");
			for(i=0;i<6;i++){
				yct.card_info.app_record.PSAM_Num[i] = recMsg.data[index++];
				//printf("%02x ",yct.card_info.app_record.PSAM_Num[i]);
			}
			//printf("\n");

			yct.card_info.app_record.RFU = (recMsg.data[index]<<8) | recMsg.data[index+1];

			//printf("##Libcard YCT## seeking card state: ok   wall_type:%02x \n",yct.card_info.wallet_type);
		};break;
		case MOC_ERROR_CARD_NOTAG:
			printf("##Libcard YCT## seeking card state: no card...\n");break;
		default:
			printf("##Libcard YCT## seeking card state: %02x\n",card_state);break;
		}

		g_card.card->errcode = 0;//通信正常
		card_state = recMsg.status;
		err_count = 0;

		pthread_mutex_unlock(g_card.card_mutex);
	}

	return NULL;
}

//初始化函数，pcard指向一个rf_card结构， plock指向pthread_mutex_t互斥量, 指向sem_t信号量,在检测到刷卡时置位。//返回0成功，1 失败
int protocol_card_init(void * pcard, void *plock, void *psem)
{
	int fd = 0;

	if((pcard==NULL) || (plock==NULL) || (psem==NULL)){
		printf("##libcard error## card init fail, due to init para NULL!\n");
		return 1;
	}

	g_card.card = (rf_card*)pcard;
	g_card.card_mutex=(pthread_mutex_t*)plock;

	if((fd = port_open(&(g_card.card->com))) == -1 )
	{
		printf("##libcard error## open device fail\n");
		return 1;
	}

	g_card.uart_fd = fd;
	port_setup(g_card.uart_fd,&(g_card.card->com));
	pthread_create(&g_card.thread_id,NULL,protocol_seek_card,NULL);

	printf("##libcard Init##uart name:%s uart baud:%d uart data_bit:%d uart parity:%d uart stop_bits:%d \n",g_card.card->com.name, g_card.card->com.baud,
			g_card.card->com.data_bits, g_card.card->com.parity, g_card.card->com.stop_bits);
	printf("##libcard Init## card source pointer:%p   libcard card pointer:%p \n",pcard,(g_card.card));

	return 0;
}


//读卡查询函数，money 返回卡余额，locknum 返回灰锁次数。
int protocol_read_card(float *money, char *locknum) //返回0成功，1 失败
{
	int count = 30;
	int i=0, j=0;
	g_card.seek_card_flag = true;

	clear_card_info();
	card_state = MOC_ERROR_CARD_NOTAG;
	yct.card_state = MOC_ERROR_CARD_NOTAG;

	isSeek_flag = true;

	while(count--){//由于该协议用寻卡来做通信检测，所以此处不需要加锁，只需要把寻卡的信息赋给UI和主控即可
		setTimer(1,0);
		if(g_card.seek_card_flag == false){
			clear_card_info();
			return 1;
		}

		if(g_card.card->errcode == 1){
			clear_card_info();
			return 1;
		}

		if(card_state == MOC_ERROR_NORMAL){
			for(j=0; j<8; j++)
				g_card.card->cardNUM[j] = yct.card_info.logicNum[j];

			g_card.card->available_money = yct.card_info.balance;
			*money = yct.card_info.balance;
			break;
		}
	}

	if(count <= 0){
		clear_card_info();
		return 1;
	}


	printf("############ Card Info ##################\n");
	printf("card.type = %x\n",g_card.card->cardtype);
	printf("card.UIDLen = %d\n",g_card.card->UIDLen);
	printf("card.cardNUM = ");
	for(i=0; i<8; i++)
		printf("%02x",g_card.card->cardNUM[i]);
	printf("\n");
	printf("card.ver = %02x\n",g_card.card->ver);
	printf("card.money = %d\n",g_card.card->available_money);
	printf("############    Card  End ##################\n");

	return 0;

}

//退出寻卡的状态
int protocol_exit_seek_card_status(void)
{
	g_card.seek_card_flag = false;
	return 0;
}

//消费指令完成扣费减值操作。
int protocol_yct_consume()
{
	struct Msg_Card_to_Terminal recMsg;
	struct Msg_Terminal_to_Card sendMsg;
	uint8 data[MAX_BUF_SIZE] = {0};
	int dataLen = 0;
	int re_len = 0;
	int index = 0;

	printf("##Libcard YCT## enter %s ...\n",__func__);
	dataLen = 0;
	memset(data,0,sizeof(data));
	memset(&sendMsg,0,sizeof(sendMsg));
	sendMsg.header = YCT_TERMINAL_STX;
	sendMsg.command = 0xE9;
	sendMsg.data[dataLen++] = yct.app_flag; //00：普通消费 01：复合消费
	sendMsg.dataLen = dataLen;
	creat_yct_frame(data,sizeof(data),&sendMsg);

	if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
		printf("##Libcard YCT## %s   send error ,line:%d\n",__func__,__LINE__);
		//		g_card.card->errcode = 1;//通信异常
		return 1;
	}

	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
	if(re_len <= 0){
		printf("##Libcard YCT##%s  listen_recv timeout or error!\n",__func__);
		//		g_card.card->errcode = 1;//通信异常
		return 1;
	}
	analysis_data(data,re_len,&recMsg);

	index = 0;
	yct.card_state = recMsg.status;
	if(recMsg.status == MOC_ERROR_NORMAL){
		if(yct.card_info.wallet_type == WALLET_CPU)
			memcpy(yct.consume_info.cpu.trade_ident_code, &recMsg.data[index],4);
		//		return 0;
	}
	else{
		printf("##Libcard YCT## %s fail, error state:%02x\n",__func__,recMsg.status);
		//		return recMsg.status;
	}
	return recMsg.status;
}

//消费预处理
int protocol_yct_consume_precondition(struct yct_card* pCard,  char recordFlag, char devState )
{
	struct Msg_Card_to_Terminal recMsg;
	struct Msg_Terminal_to_Card sendMsg;
	uint8 data[MAX_BUF_SIZE] = {0};
	int dataLen = 0;
	int re_len = 0;
	int index = 0;
	struct tm *tm_local = NULL;
	time_t tt_local;
	int ret = 0;
	static unsigned char date[7];

	printf("##Libcard YCT## enter %s ...\n",__func__);
	if(pCard == NULL)
	{
		printf("##Libcard YCT## yct consume precondition fail, due to function para is NULL!!!\n");
		return 1;
	}

	//	pthread_mutex_lock(g_card.card_mutex);
	time(&tt_local);
	tm_local=localtime(&tt_local);
	yct.consume_precondition.terminal_trade_date[0] = inttoBCD((tm_local->tm_year+1900))>>8;
	yct.consume_precondition.terminal_trade_date[1] = inttoBCD((tm_local->tm_year+1900));
	yct.consume_precondition.terminal_trade_date[2] = inttoBCD((tm_local->tm_mon+1));
	yct.consume_precondition.terminal_trade_date[3] = inttoBCD((tm_local->tm_mday));
	yct.consume_precondition.terminal_trade_time[0] = inttoBCD(tm_local->tm_hour);
	yct.consume_precondition.terminal_trade_time[1] = inttoBCD(tm_local->tm_min);
	yct.consume_precondition.terminal_trade_time[2] = inttoBCD(tm_local->tm_sec);


	yct.consume_precondition.original_trade_money = pCard->consume_precondition.original_trade_money;
	yct.consume_precondition.actual_trade_money = pCard->consume_precondition.actual_trade_money;
	memcpy(yct.consume_precondition.record.trade_serial_num, pCard->consume_precondition.record.trade_serial_num,4);


	dataLen = 0;
	memset(data,0,sizeof(data));
	memset(&sendMsg,0,sizeof(sendMsg));
	sendMsg.header = YCT_TERMINAL_STX;
	sendMsg.command = 0xE8;
	sendMsg.data[dataLen++] = yct.app_flag; //00：普通消费 01：复合消费
	sendMsg.data[dataLen++] = yct.consume_precondition.original_trade_money>>24;
	sendMsg.data[dataLen++] = yct.consume_precondition.original_trade_money>>16;
	sendMsg.data[dataLen++] = yct.consume_precondition.original_trade_money>>8;
	sendMsg.data[dataLen++] = yct.consume_precondition.original_trade_money;
	sendMsg.data[dataLen++] = yct.consume_precondition.actual_trade_money>>24;
	sendMsg.data[dataLen++] = yct.consume_precondition.actual_trade_money>>16;
	sendMsg.data[dataLen++] = yct.consume_precondition.actual_trade_money>>8;
	sendMsg.data[dataLen++] = yct.consume_precondition.actual_trade_money;
	memcpy(&sendMsg.data[dataLen],yct.consume_precondition.terminal_trade_date,4);
	dataLen += 4;
	memcpy(&sendMsg.data[dataLen],yct.consume_precondition.terminal_trade_time,3);
	dataLen += 3;
	sendMsg.data[dataLen++] = 0x00;//卡离线有效期启用
	if(yct.card_info.card_type == CARD_STUDENT)
		sendMsg.data[dataLen++] = inttoBCD(4);
	else
		sendMsg.data[dataLen++] = inttoBCD(12);

	if(yct.card_info.wallet_type == WALLET_CPU && yct.app_flag==0x01){
		sendMsg.data[dataLen++]= serverCode[0];
		sendMsg.data[dataLen++]= serverCode[1];


		sendMsg.data[dataLen++]=0x01;
		sendMsg.data[dataLen++]=recordFlag;

		sendMsg.data[dataLen++]=30;



		memcpy(&sendMsg.data[dataLen],yct.devNum,8);
		dataLen+=8;

		sendMsg.data[dataLen++]=devState;

		memcpy(&sendMsg.data[dataLen],yct.consume_precondition.record.trade_serial_num,4);
		dataLen+=4;

		if(recordFlag==2 && devState==2){
			memcpy(&sendMsg.data[dataLen], yct.card_info.app_record.trade_time, 7);
			dataLen+=7;
		}
		else{
			memcpy(&sendMsg.data[dataLen], yct.consume_precondition.terminal_trade_date, 4);
			dataLen+=4;
			memcpy(&sendMsg.data[dataLen], yct.consume_precondition.terminal_trade_time, 3);
			dataLen+=3;
		}

		memcpy(&sendMsg.data[dataLen],yct.PSAM,6);
		dataLen+=6;

		if(recordFlag==1 && devState==1){
			dataLen+=2;
		}
		else{
			sendMsg.data[dataLen++] = yct.card_info.app_record.RFU;
			sendMsg.data[dataLen++] = (yct.card_info.app_record.RFU>>8);
		}

		dataLen+=2;
	}
	else if(yct.card_info.wallet_type == WALLET_M1)
		dataLen += 0;//卡片将不会写拓展应用复合记录
	else
		dataLen += 35; //暂不进行拓展应用  相应数据填全0

	sendMsg.dataLen = dataLen;
	creat_yct_frame(data,sizeof(data),&sendMsg);

	if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
		printf("##Libcard YCT## %s   send error ,line:%d\n",__func__,__LINE__);
		//		g_card.card->errcode = 1;//通信异常
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
	if(re_len <= 0){
		printf("##Libcard YCT##%s  listen_recv timeout or error!\n",__func__);
		//		g_card.card->errcode = 1;//通信异常
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}
	analysis_data(data,re_len,&recMsg);
	yct.card_state = recMsg.status;
	if(recMsg.status == MOC_ERROR_NORMAL){
		printf("##Libcard YCT## %s  success!!!\n",__func__);
		index = 0;
		if(yct.card_info.wallet_type == WALLET_M1){
			memcpy(yct.consume_info.m1.terminal_trade_serial_num, &recMsg.data[index],4);
			index += 4;

			memcpy(yct.consume_info.m1.logic_cardNum, &recMsg.data[index],8);
			index += 8;

			memcpy(yct.consume_info.m1.cardNum, &recMsg.data[index],8);
			index += 8;

			memcpy(yct.consume_info.m1.last_trade_devNum, &recMsg.data[index],4);
			index += 4;

			memcpy(yct.consume_info.m1.last_trade_time, &recMsg.data[index],7);
			index += 7;

			memcpy(yct.consume_info.m1.SAM_logiv_num, &recMsg.data[index],4);
			index += 4;

			memcpy(yct.consume_info.m1.cur_trade_time, &recMsg.data[index],7);
			index += 7;

			yct.consume_info.m1.trade_money = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.m1.balance = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.m1.ticket_price = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.m1.trade_type = recMsg.data[index++];

			yct.consume_info.m1.ticket_count = (recMsg.data[index]<<8) | (recMsg.data[index+1]);
			index += 2;

			yct.consume_info.m1.add_door_mounth[0] = recMsg.data[index++];
			yct.consume_info.m1.add_door_mounth[1] = recMsg.data[index++];

			yct.consume_info.m1.bus_door_count = recMsg.data[index++];
			yct.consume_info.m1.subway_door_count = recMsg.data[index++];
			yct.consume_info.m1.joint_multiplication = recMsg.data[index++];

			memcpy(yct.consume_info.m1.trade_door_devNum,&recMsg.data[index],4);
			index += 4;

			memcpy(yct.consume_info.m1.trade_door_time,&recMsg.data[index],7);
			index += 7;

			memcpy(yct.consume_info.m1.trade_ident_code,&recMsg.data[index],4);

		}
		else if(yct.card_info.wallet_type == WALLET_CPU){
			memcpy(yct.consume_info.cpu.trade_devNum, &recMsg.data[index],6);
			index += 6;

			memcpy(yct.consume_info.cpu.terminal_trade_serial_num, &recMsg.data[index],4);
			index += 4;

			memcpy(yct.consume_info.cpu.cur_trade_time, &recMsg.data[index],7);
			index += 7;

			memcpy(yct.consume_info.cpu.logic_cardNum, &recMsg.data[index],8);
			index += 8;

			memcpy(yct.consume_info.cpu.cardNum, &recMsg.data[index], 8);
			index += 8;

			yct.consume_info.cpu.trade_money = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.cpu.ticket_price = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.cpu.balance = (recMsg.data[index]<<24) | (recMsg.data[index+1]<<16) | (recMsg.data[index+2]<<8) | recMsg.data[index+3];
			index += 4;

			yct.consume_info.cpu.trade_type = recMsg.data[index++];
			yct.consume_info.cpu.add_trade_type = recMsg.data[index++];

			yct.consume_info.cpu.ticket_recharge_count = (recMsg.data[index]<<8) | recMsg.data[index+1];
			index += 2;

			yct.consume_info.cpu.ticket_consume_count = (recMsg.data[index]<<8) | recMsg.data[index+1];
			index += 2;

			yct.consume_info.cpu.add_door_mounth[0] = recMsg.data[index++];
			yct.consume_info.cpu.add_door_mounth[1] = recMsg.data[index++];

			yct.consume_info.cpu.bus_door_count = recMsg.data[index++];
			yct.consume_info.cpu.subway_door_count = recMsg.data[index++];
			yct.consume_info.cpu.joint_multiplication = recMsg.data[index++];

			memcpy(yct.consume_info.cpu.trade_door_devNum,&recMsg.data[index],6);
			index += 6;

			memcpy(yct.consume_info.cpu.trade_door_time,&recMsg.data[index],7);
			index += 7;

			memcpy(yct.consume_info.cpu.last_trade_devNum,&recMsg.data[index],6);
			index += 6;

			memcpy(yct.consume_info.cpu.last_trade_time,&recMsg.data[index],4);
			index += 4;

			yct.consume_info.cpu.area_code = recMsg.data[index];

			yct.consume_info.cpu.area_card_type = (recMsg.data[index]<<8)|(recMsg.data[index+1]);
			index += 2;


			yct.consume_info.cpu.area_sub_code = recMsg.data[index++];

			memcpy(yct.consume_info.cpu.trade_ident_code,&recMsg.data[index],4);
		}
		else{
			printf("##Libcard YCT## %s fail,due to wallet type no exist, wallet type=%02d\n",__func__,yct.card_info.wallet_type);
			pthread_mutex_unlock(g_card.card_mutex);
			return  recMsg.status;
		}
	}
	else{
		if(recMsg.status == MOC_ERROR_CARD_OVERLIMIT)
			printf("##Libcard YCT## %s fail, due to wallet balance overlimit!\n",__func__);
		else if(recMsg.status == MOC_ERROR_CARD_OWEPAY)
			printf("##Libcard YCT## %s fail, due to wallet balance is not enough!\n",__func__);
		else if(recMsg.status == MOC_ERROR_CARD_OUTOF_DATE)
			printf("##Libcard YCT## %s fail, due to card over valid date or over offline valid date!\n",__func__);
		else if(recMsg.status == MOC_ERROR_CARDTIMEOUT_MONTH)
			printf("##Libcard YCT## %s fail, due to card offline month para illegal!\n",__func__);
		else if(recMsg.status == MOC_ERROR_CARD_NOTAG)
			printf("##Libcard YCT## %s fail, due to no card...!\n",__func__);
		else
			printf("##Libcard YCT## %s fail, card error state:%02x\n",__func__,recMsg.status);
		pthread_mutex_unlock(g_card.card_mutex);

		return recMsg.status;

	}

	pthread_mutex_unlock(g_card.card_mutex);
	return 0;
}

//未完整交易处理
int protocol_yct_incomplete_consume_deal(struct yct_card* pCard,unsigned char *TAC, int tac_len)
{
	struct Msg_Card_to_Terminal recMsg;
	struct Msg_Terminal_to_Card sendMsg;
	uint8 data[MAX_BUF_SIZE] = {0};
	int dataLen = 0;
	int re_len = 0;
	int index = 0;

	printf("##Libcard YCT## enter %s ...\n",__func__);
	if (pCard == NULL || TAC==NULL || tac_len<4){
		printf("##Libcard YCT## %s fail, due to function para is NULL!\n ",__func__);
		return 1;
	}

	pthread_mutex_lock(g_card.card_mutex);

	memset(&(yct.incomplete_trade), 0 ,sizeof(yct.incomplete_trade));
	memcpy(&(yct.incomplete_trade), &(pCard->incomplete_trade),sizeof(yct.incomplete_trade));

	printf("#libcard# %s  trade_money=%d   balance=%d\n",__func__,yct.incomplete_trade.trade_money,yct.incomplete_trade.balance);
	dataLen = 0;
	memset(data,0,sizeof(data));
	memset(&sendMsg,0,sizeof(sendMsg));
	sendMsg.header = YCT_TERMINAL_STX;
	sendMsg.command = 0xEA;
	sendMsg.data[dataLen++] = yct.app_flag; //00：普通消费 01：复合消费

	memcpy(&sendMsg.data[dataLen],yct.incomplete_trade.logic_cardNum,8);
	dataLen += 8;

	memcpy(&sendMsg.data[dataLen],yct.incomplete_trade.cardNum,8);
	dataLen += 8;

	sendMsg.data[dataLen++] = yct.incomplete_trade.ticket_trade_count>>8;
	sendMsg.data[dataLen++] = yct.incomplete_trade.ticket_trade_count;
	sendMsg.data[dataLen++] = yct.incomplete_trade.trade_money>>24;
	sendMsg.data[dataLen++] = yct.incomplete_trade.trade_money>>16;
	sendMsg.data[dataLen++] = yct.incomplete_trade.trade_money>>8;
	sendMsg.data[dataLen++] = yct.incomplete_trade.trade_money;
	sendMsg.data[dataLen++] = yct.incomplete_trade.balance>>24;
	sendMsg.data[dataLen++] = yct.incomplete_trade.balance>>16;
	sendMsg.data[dataLen++] = yct.incomplete_trade.balance>>8;
	sendMsg.data[dataLen++] = yct.incomplete_trade.balance;

	sendMsg.dataLen = dataLen;
	creat_yct_frame(data,sizeof(data),&sendMsg);

	if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
		printf("##Libcard YCT## %s   send error ,line:%d\n",__func__,__LINE__);
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}

	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
	if(re_len <= 0){
		printf("##Libcard YCT##%s  listen_recv timeout or error!\n",__func__);
		pthread_mutex_unlock(g_card.card_mutex);
		return -1;
	}
	analysis_data(data,re_len,&recMsg);
	yct.card_state = recMsg.status;
	index = 0;
	if(recMsg.status == MOC_ERROR_NORMAL){
		memcpy(TAC,&recMsg.data[index],4);
	}
	else if(recMsg.status == MOC_ERROR_NO_RECORD){
		printf("##Libcard YCT## %s fail, due to no record!\n",__func__);
		pthread_mutex_unlock(g_card.card_mutex);
		return recMsg.status;
	}
	else{
		printf("##Libcard YCT## %s fail, error state:%02x\n",__func__, recMsg.status);
		pthread_mutex_unlock(g_card.card_mutex);
		return recMsg.status;
	}

	pthread_mutex_unlock(g_card.card_mutex);
	return recMsg.status;
}

int protocol_yct_catch_blacklist_card(void)
{
	struct Msg_Card_to_Terminal recMsg;
	struct Msg_Terminal_to_Card sendMsg;
	uint8 data[MAX_BUF_SIZE] = {0};
	int dataLen = 0;
	int re_len = 0;

	printf("##Libcard YCT## enter %s ...\n",__func__);
	pthread_mutex_lock(g_card.card_mutex);
	dataLen = 0;
	memset(data,0,sizeof(data));
	memset(&sendMsg,0,sizeof(sendMsg));
	sendMsg.header = YCT_TERMINAL_STX;
	sendMsg.command = 0xB8;
	sendMsg.dataLen = dataLen;
	creat_yct_frame(data,sizeof(data),&sendMsg);

	if((uart_send(g_card.uart_fd, data,sendMsg.frameLen)) < 0){
		printf("##Libcard YCT## %s   send error ,line:%d\n",__func__,__LINE__);
		//		g_card.card->errcode = 1;//通信异常
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}

	memset(data,0,sizeof(data));
	re_len = listen_recv(g_card.uart_fd, data, sizeof(data),1000);
	if(re_len <= 0){
		printf("##Libcard YCT##%s  listen_recv timeout or error!\n",__func__);
		//		g_card.card->errcode = 1;//通信异常
		pthread_mutex_unlock(g_card.card_mutex);
		return 1;
	}
	analysis_data(data,re_len,&recMsg);
	yct.card_state = recMsg.status;
	if(recMsg.status == MOC_ERROR_NORMAL){
		printf("##Libcard YCT## %s success!\n",__func__);
	}
	else if(recMsg.status == MOC_ERROR_CARD_SETBLACKLIST){
		printf("##Libcard YCT## %s fail, due to set blacklist card error!\n",__func__);
		pthread_mutex_unlock(g_card.card_mutex);
		return recMsg.status;
	}
	else{
		printf("##Libcard YCT## %s fail, error state:%02x\n",__func__, recMsg.status);
		pthread_mutex_unlock(g_card.card_mutex);
		return recMsg.status;
	}

	pthread_mutex_unlock(g_card.card_mutex);
	return recMsg.status;
}

void switch_value(yct_rf_consum_card* card_info)
{

	if(yct.card_info.wallet_type == WALLET_CPU){
		memcpy(card_info->cur_tr_devNum, yct.consume_info.cpu.trade_devNum,6);
		memcpy(card_info->terminal_sernum, yct.consume_info.cpu.terminal_trade_serial_num,4);
		memcpy(card_info->cur_trade_date, yct.consume_info.cpu.cur_trade_time,7);
		memcpy(card_info->logic_card_Num, yct.consume_info.cpu.logic_cardNum,8);
		memcpy(card_info->phy_card_Num, yct.consume_info.cpu.cardNum,8);
		card_info->real_money = yct.consume_info.cpu.trade_money;
		card_info->org_money = yct.consume_info.cpu.ticket_price;
		card_info->cur_balance = yct.consume_info.cpu.balance;
		card_info->tr_type = yct.consume_info.cpu.trade_type;
		card_info->attach_tr_type = yct.consume_info.cpu.add_trade_type;
		card_info->recharge_count = yct.consume_info.cpu.ticket_recharge_count;
		card_info->consum_count = yct.consume_info.cpu.ticket_consume_count;
		memcpy(card_info->addup_mon, yct.consume_info.cpu.add_door_mounth,2);
		card_info->bus_count = yct.consume_info.cpu.bus_door_count;
		card_info->subway_count = yct.consume_info.cpu.subway_door_count;
		card_info->conn_count = yct.consume_info.cpu.joint_multiplication;
		memcpy(card_info->cur_tr_enter_devNum, yct.consume_info.cpu.trade_door_devNum,6);
		memcpy(card_info->cur_tr_enter_date, yct.consume_info.cpu.trade_door_time,7);
		memcpy(card_info->last_tr_devNum, yct.consume_info.cpu.last_trade_devNum,6);
		memcpy(card_info->last_tr_time, yct.consume_info.cpu.last_trade_time,4);
		card_info->area_code = yct.consume_info.cpu.area_code;
		card_info->area_card_type = yct.consume_info.cpu.area_card_type;
		card_info->area_son_code = yct.consume_info.cpu.area_sub_code;
		memcpy(card_info->TAC, yct.consume_info.cpu.trade_ident_code,4);
	}
	else if(yct.card_info.wallet_type == WALLET_M1){
		memcpy(card_info->terminal_sernum, yct.consume_info.m1.terminal_trade_serial_num,4);
		memcpy(card_info->logic_card_Num, yct.consume_info.m1.logic_cardNum,8);
		memcpy(card_info->phy_card_Num, yct.consume_info.m1.cardNum,8);
		memcpy(card_info->last_tr_devNum, yct.consume_info.m1.last_trade_devNum,4);
		memcpy(card_info->last_tr_time, &yct.consume_info.m1.last_trade_time[2],4);
		memcpy(card_info->cur_tr_devNum, yct.consume_info.m1.SAM_logiv_num,4);
		memcpy(card_info->cur_trade_date, yct.consume_info.m1.cur_trade_time,7);
		card_info->real_money = yct.consume_info.m1.trade_money;
		card_info->cur_balance = yct.consume_info.m1.balance;
		card_info->org_money = yct.consume_info.m1.ticket_price;
		card_info->tr_type = yct.consume_info.m1.trade_type;
		card_info->consum_count = yct.consume_info.m1.ticket_count;
		memcpy(card_info->addup_mon , yct.consume_info.m1.add_door_mounth,2);
		card_info->bus_count = yct.consume_info.m1.bus_door_count;
		card_info->subway_count = yct.consume_info.m1.subway_door_count;
		card_info->conn_count = yct.consume_info.m1.joint_multiplication;
		memcpy(card_info->cur_tr_enter_devNum, yct.consume_info.m1.trade_door_devNum,4);
		memcpy(card_info->cur_tr_enter_date, yct.consume_info.m1.trade_door_time,7);
		memcpy(card_info->TAC, yct.consume_info.m1.trade_ident_code,4);
	}

}

/*
 * 作用：锁卡，并获取当前卡片的交易信息   下发充电指令之前需要调用该函数锁卡
 *预消费  org_money原交易金额 (以分为单位)   real_money实际交易金额 (以分为单位) 由UI填充
 *预消费  card_info该形参由读卡器进行填充，该指针不能为空或野指针，读卡器填充
 *预消费  返回成功时，返回失败时禁止充电，返回成功允许充电；  返回失败时需要提示刷卡结算，解卡
 *预消费   成功返回0; 填充的card_info需UI交给主控，将羊城通信息上报后台
 *预消费  失败原因 1(钱包余额不足)  2(卡片超出有效期)  3(未感应到卡片)  4(卡片已锁)   5读卡器故障 其他刷卡返回失败原因
 **/
int protocol_yct_card_preconsume(int org_money, int real_money,  yct_rf_consum_card* card_info)
{
	struct yct_card  trcard;
	int ret = 0;
	int i=0;
	int count=30;

	if( card_info==NULL){
		printf("##Libcard YCT## %s fail, due to para is NULL!!!\n",__func__);
		return -1;
	}

	memset(card_info,0 ,sizeof(yct_rf_consum_card));

	yct.card_state = MOC_ERROR_CARD_NOTAG;
	while(count--){//此处寻卡
		setTimer(1,0);
		if(g_card.card->errcode == 1)
			return 5;

		if(yct.card_state != MOC_ERROR_NORMAL)
			continue;
		else
			break;
	}

	if(count <= 0){
		return 3;
	}

	if(yct.card_info.app_record.record_flag == 0x01){
		printf("##Libcard YCT## %s fail, due to card is already lock!!!\n",__func__);
		return 4;
	}

	isSeek_flag = false;//预处理期间暂时关闭寻卡

	memset(&trcard, 0, sizeof(struct yct_card));
	trcard.consume_precondition.original_trade_money = org_money;
	trcard.consume_precondition.actual_trade_money = real_money;

	for(i=0; i<5; i++){
		ret = protocol_yct_consume_precondition(&trcard,0x01,0x01);
		if (ret == 0)
			break;
		else if(ret == MOC_ERROR_CARD_OWEPAY){
			ret = 1;
			break;
		}
		else if(ret== MOC_ERROR_CARD_OUTOF_DATE){
			ret = 2;
			break;
		}
		else if(ret== MOC_ERROR_CARD_NOTAG){
			ret = 3;
		}
		else if(ret == MOC_ERROR_TS_STEP){
			isSeek_flag=true;
			setTimer(2,0);
			isSeek_flag=false;
		}

		setTimer(0,500);
	}	

	isSeek_flag = true;//结束打开寻卡

	if(ret == MOC_ERROR_NORMAL){
		printf("##Libcard YCT## %s  success!!!\n",__func__);
		switch_value(card_info);
		ret =  protocol_yct_consume();
	}
	else
		printf("##Libcard YCT## %s  failed!!!\n",__func__);

	return ret;
}


/*
 * 结算交易  org_money原交易金额(即设置充电金额 以分为单位)   real_money实际交易金额 (以分为单位),  成功返回0
 * 失败原因 1(未感应到卡) 其他失败原因  如果结算失败，应继续等待重新刷卡，重新结算
 * */
int protocol_yct_card_settle_accounts(int org_money, int real_money,yct_rf_consum_card* card_info)
{
	int ret = 0;
	struct yct_card  trcard;
	memset(&trcard, 0, sizeof(struct yct_card));
	int i=0;
	int count=30;

	if( card_info==NULL){
		printf("##Libcard YCT## %s fail, due to para is NULL!!\n!",__func__);
		return -1;
	}

	yct.card_state = MOC_ERROR_CARD_NOTAG;
	while(count--){//此处寻卡
		setTimer(1,0);
		if(g_card.card->errcode == 1)
			return 5;
		if(yct.card_state != MOC_ERROR_NORMAL)
			continue;
		else
			break;
	}

	if(count <= 0){
		return 3;
	}

	isSeek_flag = false;//结算期间暂停寻卡

	trcard.consume_precondition.original_trade_money = org_money;
	trcard.consume_precondition.actual_trade_money = real_money;//1分钱

	for(i=0; i<5; i++){
		ret = protocol_yct_consume_precondition(&trcard,0x02,0x02);
		if (ret == 0){
			ret =  protocol_yct_consume();
			break;
		}
		setTimer(0,500);
	}

	isSeek_flag = true;//结算完成恢复寻卡

	if(ret == MOC_ERROR_NORMAL){
		printf("##Libcard YCT## %s  success!!!\n",__func__);
		switch_value(card_info);
	}
	else
		printf("##Libcard YCT## %s  failed!!!\n",__func__);

	return ret;
}

int protocol_yct_card_incomplete_settle(yct_incomplete_trade* record, unsigned char tac[4])
{
	int count=30;
	int ret = 0;
	struct yct_card  incard;

	if(record==NULL || tac==NULL){
		printf("##Libcard YCT## %s fail, due to para is NULL!!!\n",__func__);
		return -1;
	}

	memcpy(&incard.incomplete_trade, record, sizeof(yct_incomplete_trade));
	isSeek_flag = true;

	yct.card_state = MOC_ERROR_CARD_NOTAG;
	while(count--){//此处寻卡
		setTimer(1,0);
		if(g_card.card->errcode == 1)
			return 5;

		if(yct.card_state != MOC_ERROR_NORMAL)
			continue;
		else
			break;
	}

	if(count <= 0){
		return 3;
	}

	/*
	isSeek_flag = false;
	printf("#libcard# %s  trade_money=%d   balance=%d\n",__func__,record->trade_money,record->balance);
	ret = protocol_yct_incomplete_consume_deal(&incard, tac, 4);
	 */

	/*
	if(ret != MOC_ERROR_NORMAL){
		printf("##Libcard YCT## %s fail !!! go to direct settle !!!!\n",__func__);
		yct_rf_consum_card card_info;
		isSeek_flag = true;
		ret = protocol_yct_card_settle_accounts(0,record->trade_money,&card_info);
		if(ret == MOC_ERROR_NORMAL)
			memcpy(tac,card_info.TAC,4);
	}
	 */

	yct_rf_consum_card card_info;
	ret = protocol_yct_card_settle_accounts(0,record->trade_money,&card_info);
	if(ret == MOC_ERROR_NORMAL)
		memcpy(tac,card_info.TAC,4);

//	isSeek_flag = true;
	return ret;
}

int protocol_yct_card_set_info(char psam[6], char devNum[8])
{

	if (psam==NULL  || devNum==NULL){
		printf("##Libcard YCT## %s fail, due to para is NULL!!!\n",__func__);
		return -1;
	}

	memcpy(yct.PSAM,psam,6);
	memcpy(yct.devNum,devNum,8);

#ifdef DEDUCTION_FEE
	//	unsigned char psam[6]={0x01,0x00,0x00,0x16,0x12,0x18};
	//	memcpy(yct.PSAM,psam,6);
	//	unsigned char devNum[8]={0x44,0x48,0x00,0x00,0x00,0x00,0x22,0x34};
	//	memcpy(yct.devNum,devNum,8);

	yct.app_flag = 0x01;
#else
	yct.app_flag = 0x00;
#endif

	return 0;
}

int protocol_yct_card_catch_blacklist()
{
	int count=3;
	int ret = 0;

	yct.card_state = MOC_ERROR_CARD_NOTAG;
	while(count--){//此处寻卡
		setTimer(1,0);
		if(g_card.card->errcode == 1)
			return 5;

		if(yct.card_state != MOC_ERROR_NORMAL)
			continue;
		else
			break;
	}

	if(count <= 0){
		return 3;
	}

	isSeek_flag = false;
	ret = protocol_yct_catch_blacklist_card();
	if(ret ==MOC_ERROR_CARD_SETBLACKLIST)
		ret = 1;
	if(ret == 0)
		printf("##Libcard YCT## %s  success!!!\n",__func__);
	else
		printf("##Libcard YCT## %s  failed!!!\n",__func__);

	isSeek_flag = true;

	return ret;
}














